using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.ComponentModel;
using System.Web;
using System.Drawing;
[assembly: WebResource("Library.WebControls.AdvHiddenField.include.AdHiddenField.js", "text/javascript")]
namespace Library.WebControls.AdvHiddenField {
	[Designer(typeof(AdvHiddenFieldDesign))]
	[ToolboxBitmap(typeof(AdvHiddenField), "Library.WebControls.AdvHiddenField.AdvHiddenField.bmp")]
	[ToolboxData("<{0}:AdvHiddenField runat=server></{0}:AdvHiddenField>")]
	public class AdvHiddenField : Control {
		public static readonly Type AdvHiddenFieldType = typeof(AdvHiddenField);
		public const string SplitKeyValue = "-|;!.";
		public const string SplitObject = "_|-;,";
		private System.Collections.Specialized.StringDictionary internaDic;
		private System.Web.UI.WebControls.HiddenField hiddenField;
		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			if (Page != null) {
				LoadDataFromRequest();
			}
		}

		public override string ID {
			get {
				EnsureChildControls();
				return hiddenField.ID;
			}
			set {
				EnsureChildControls();
				hiddenField.ID = value;
			}
		}

		protected override void CreateChildControls() {
			hiddenField = new System.Web.UI.WebControls.HiddenField();			
			Controls.Add(hiddenField);
		}

    /// <summary>
    /// Add key and value for hiddend field
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
		public void Add(string key, string value) {
			InternalDataDictionary.Add(key, value);
		}

    /// <summary>
    /// remove a key from hiddend field
    /// </summary>
    /// <param name="key"></param>
		public void Remove(string key) {
			InternalDataDictionary.Remove(key);
		}
    /// <summary>
    /// Clear all value from hiddend field
    /// </summary>
		public void Clear() {
			InternalDataDictionary.Clear();
		}
    /// <summary>
    /// Get value by the key
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
		public string Get(string key) {
			return InternalDataDictionary[key];
		}

    /// <summary>
    /// Check if the hidden field contain the key or not
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
		public bool ContainsKey(string key) {
			return InternalDataDictionary.ContainsKey(key);
		}
		private string Value {
			get {
				EnsureChildControls();
				return hiddenField.Value;
			}
		}

		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);
			if (!Page.ClientScript.IsClientScriptIncludeRegistered(AdvHiddenFieldType, "Hidden")) {
				Page.ClientScript.RegisterClientScriptInclude(AdvHiddenFieldType, "Hidden", Page.ClientScript.GetWebResourceUrl(AdvHiddenFieldType,
												 "Library.WebControls.AdvHiddenField.include.AdHiddenField.js"));
			}
		}

		private void LoadDataFromRequest() {
			if (DesignMode) {
				return;
			}

			string value = Value;
			if (String.IsNullOrEmpty(value)) {
				if (Page != null) {
					EnsureChildControls();
					value = Page.Request[hiddenField.ID];
				}
			}


			if (String.IsNullOrEmpty(value)) {
				return;
			}

			InternalDataDictionary.Clear();
			string[] objs = value.Split(new string[] { SplitObject }, StringSplitOptions.RemoveEmptyEntries);
			if (objs.Length > 0) {
				foreach (string obj in objs) {
					string[] kvs = obj.Split(new string[] { SplitKeyValue }, StringSplitOptions.None);
					if (kvs.Length == 2) {
						internaDic.Add(kvs[0], kvs[1]);
					}
				}
			}
		}

		private System.Collections.Specialized.StringDictionary InternalDataDictionary {
			get {
				if (internaDic == null) {
					internaDic = new System.Collections.Specialized.StringDictionary();
					LoadDataFromRequest();
				}
				return internaDic;

			}
		}


		public IList<KeyValuePair<string, string>> GetAll() {
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			string[] keys = new string[InternalDataDictionary.Keys.Count];
			string[] values = new string[InternalDataDictionary.Values.Count];
			InternalDataDictionary.Keys.CopyTo(keys, 0);
			InternalDataDictionary.Values.CopyTo(values, 0);
			for (int i = 0; i < keys.Length; i++) {
				list.Add(new KeyValuePair<string, string>(keys[i], values[i]));
			}

			return list;
		}

		protected override void Render(HtmlTextWriter writer) {
			if (!Visible) {
				return;
			}

			StringBuilder str = new StringBuilder();
			str.Append("<script language='javascript' type='text/javascript'>");
			str.Append(String.Format("var {0}=new AdHiddenField();window['{0}']={0};", ClientInstanceName));
			str.Append(String.Format("{0}.Init();", ClientInstanceName));
			EnsureChildControls();
			str.Append(String.Format("{0}._clientId='{1}';", ClientInstanceName, hiddenField.ClientID));
			str.Append(String.Format("{0}._splitObj='{1}';", ClientInstanceName, SplitObject));
			str.Append(String.Format("{0}._splitKV='{1}';", ClientInstanceName, SplitKeyValue));
			IList<KeyValuePair<string, string>> datas = GetAll();
			HttpServerUtility server = Page != null ? Page.Server : null;
			if (server != null) {
				foreach (KeyValuePair<string, string> kv in datas) {
					str.Append(String.Format("{0}.Add('{1}', '{2}');", ClientInstanceName, server.HtmlEncode(kv.Key), server.HtmlEncode(kv.Value)));
				}
			} else {
				foreach (KeyValuePair<string, string> kv in datas) {
					str.Append(String.Format("{0}.Add('{1}', '{2}');", ClientInstanceName, kv.Key, kv.Value));
				}
			}
			str.Append("</script>");
			writer.WriteLine(str.ToString());
			hiddenField.Value = String.Empty;
			base.Render(writer);
		}
		private string clientInstanceName;
		public string ClientInstanceName {
			get {
				if (String.IsNullOrEmpty(clientInstanceName)) {
					clientInstanceName = ClientID + "_ins";
				}
				return clientInstanceName;
			}
			set {
				clientInstanceName = value;
			}
		}
	}
}
